package com.dom.stor.modular.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dom.common.constants.ConstantError;
import com.dom.common.enums.PubStatEnum;
import com.dom.common.enums.StorMsgTypeEnum;
import com.dom.common.enums.VerfyStatEnum;
import com.dom.common.exception.ServiceException;
import com.dom.common.model.vo.stor.*;
import com.dom.common.utils.BeanUtil;
import com.dom.stor.dao.entity.TGoodsInfo;
import com.dom.stor.dao.entity.TsStockInDetailFlow;
import com.dom.stor.dao.entity.TsStockInFlow;
import com.dom.stor.dao.service.*;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 入库单服务
 * @Author xllei
 * @Date 2018/12/21 3:05 PM
 * @Version 1.0
 **/
@Slf4j
@Service
public class StockinService {
    @Autowired
    private ITsStockInFlowService stockInFlowService;
    @Autowired
    private ITsStockInDetailFlowService stockInDetailFlowService;
    @Autowired
    private ITTradeDateService tradeDateService;
    @Autowired
    private ITGoodsInfoService goodsInfoService;
    @Autowired
    private ITGoodStandardTblService goodStandardTblService;
    @Autowired
    private ITGoodVarietyTblService goodVarietyTblService;
    @Autowired
    private ITMeasureUnitTblService measureUnitTblService;
    @Autowired
    private ITStorInfoService storInfoService;
    @Autowired
    private ITOrganInfoService organInfoService;
    @Autowired
    private ITUserInfoService userInfoService;
    @Autowired
    private ITsStorGoodsInfoService storGoodsInfoService;
    @Autowired
    private ITsStorGoodsDetailInfoService storGoodsDetailInfoService;
    @Autowired
    private ITsStorMsgFlowService storMsgFlowService;

    /**
     * 分页查询入库单
     *
     * @param request
     * @return
     */
    public S019A findStockinPager(S019R request) {
        Page<TsStockInFlow> pager = new Page<>();
        Wrapper<TsStockInFlow> wrapper = new EntityWrapper<>();

        //赋值分页信息
        pager.setCurrent(request.getPn());
        pager.setSize(request.getPs() != 0 ? request.getPs() : 20);

        //赋值查询条件
        wrapper.eq("mem_code", request.getMemCode());
        if (ObjectUtil.isNotNull(request.getStockDate())) {
            wrapper.and().eq("stock_date", request.getStockDate());
        }
        if (ObjectUtil.isNotNull(request.getStockType())) {
            wrapper.and().eq("stock_type", request.getStockType());
        }
        if (ObjectUtil.isNotNull(request.getStorCode())) {
            wrapper.and().eq("stor_code", request.getStorCode());
        }
        if (ObjectUtil.isNotNull(request.getOrganCode())) {
            wrapper.and().eq("organ_code", request.getOrganCode());
        }
        if (ObjectUtil.isNotNull(request.getStat())) {
            wrapper.and().eq("stat", request.getStat());
        }
        if (ObjectUtil.isNotNull(request.getVerfyStat())) {
            wrapper.and().eq("verfy_stat", request.getVerfyStat());
        }

        pager = stockInFlowService.selectPage(pager, wrapper);


        //赋值仓库、机构名称
        Map<Integer, String> storNameList = storInfoService.getStorNameList(request.getMemCode());
        Map<Integer, String> organNameList = organInfoService.getOrganNameList(request.getMemCode());
        Map<Integer, String> userNameList = userInfoService.getUserNameList(request.getMemCode());

        //获取仓库、机构信息
        List<StockinInfo> stockinInfos = new ArrayList<>();
        pager.getRecords().forEach(entity -> {
            StockinInfo stockinInfo = new StockinInfo();
            BeanUtil.copyPropertiesIgnoreNull(entity, stockinInfo);
            stockinInfo.setStockId(entity.getId());
            stockinInfo.setStockDate(DateUtil.format(entity.getStockDate(), "yyyy-MM-dd"));
            stockinInfo.setMakeDate(DateUtil.format(entity.getMakeDate(), "yyyy-MM-dd HH:mm:ss"));
            stockinInfo.setExchDate(DateUtil.format(entity.getExchDate(), "yyyy-MM-dd"));
            stockinInfo.setVerfyDate(DateUtil.format(entity.getVerfyDate(), "yyyy-MM-dd HH:mm:ss"));
            stockinInfo.setMakerId(entity.getDocuMakerId());

            stockinInfo.setStorName(storNameList.get(entity.getStorCode()));
            stockinInfo.setOrganName(organNameList.get(entity.getOrganCode()));
            stockinInfo.setMakerName(userNameList.get(entity.getDocuMakerId()));

            stockinInfos.add(stockinInfo);
        });

        S019A response = new S019A();
        response.setTotalNum((int) pager.getTotal());
        response.setStockinInfos(stockinInfos);
        return response;
    }

    /**
     * 新增入库单及明细
     *
     * @param request
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public S010A addStockinBill(S010R request) {
        TsStockInFlow stockInFlow = new TsStockInFlow();
        BeanUtil.copyPropertiesIgnoreNull(request, stockInFlow);
        stockInFlow.setStockDate(DateUtil.parse(request.getStockDate(), "yyyy-MM-dd"));
        stockInFlow.setOrganCode(request.getOrgId());
        stockInFlow.setDocuMakerId(request.getOperId());
        stockInFlow.setMakeDate(new Date());
        stockInFlow.setExchDate(tradeDateService.getExchDate(request.getMemCode()));
        stockInFlow.setStat(PubStatEnum.STAT_NORMAL.getCode());
        stockInFlow.setVerfyStat(PubStatEnum.STAT_NORMAL.getCode());
        stockInFlow.setCancelStat(PubStatEnum.STAT_NORMAL.getCode());

        boolean result = stockInFlowService.insert(stockInFlow);
        if (!result) {
            log.warn("录入入库单异常", result);
            throw new ServiceException(ConstantError.DATAERROR);
        }

        //批量录入入库单明细
        addStockinDetail(request, stockInFlow);

        S010A response = new S010A();
        response.setStockId(stockInFlow.getStockId());
        return response;
    }

    /**
     * 增加入库单明细
     *
     * @param request
     * @param stockInFlow
     * @return
     */
    private boolean addStockinDetail(S010R request, TsStockInFlow stockInFlow) {
        //获取商品信息
        Map<Integer, TGoodsInfo> goodsList = goodsInfoService.getGoodInfoList(request.getMemCode());
        Map<Integer, String> standardNameList = goodStandardTblService.getStandardNameList(request.getMemCode());
        Map<Integer, String> varietyNameList = goodVarietyTblService.getVarietyNameList(request.getMemCode());
        Map<Integer, String> unitList = measureUnitTblService.getUnitList(request.getMemCode());


        List<TsStockInDetailFlow> stockInDetailFlows = new ArrayList<>();
        request.getStockDetailInfos().forEach(detailItem -> {
            TsStockInDetailFlow stockInDetailFlow = new TsStockInDetailFlow();
            BeanUtil.copyPropertiesIgnoreNull(detailItem, stockInDetailFlow);
            stockInDetailFlow.setMemCode(request.getMemCode());
            stockInDetailFlow.setStat(PubStatEnum.STAT_NORMAL.getCode());
            stockInDetailFlow.setStockId(stockInFlow.getId().toString());

            //赋值商品信息
            TGoodsInfo goodInfo = goodsList.get(detailItem.getGoodCode());
            stockInDetailFlow.setGoodName(goodInfo.getGoodName());
            stockInDetailFlow.setVarietyCode(goodInfo.getVarietyCode());
            stockInDetailFlow.setVarietyName(varietyNameList.get(goodInfo.getVarietyCode()));
            stockInDetailFlow.setStandardName(standardNameList.get(goodInfo.getStandardCode()));
            stockInDetailFlow.setUnit(unitList.get(goodInfo.getUnitCode()));

            stockInDetailFlows.add(stockInDetailFlow);
        });
        boolean result = stockInDetailFlowService.insertBatch(stockInDetailFlows);
        if (!result) {
            log.info("批量录入入库单明细失败", result);
            throw new ServiceException(ConstantError.DATAERROR);
        }
        return result;
    }

    /**
     * 更新入库单信息及明细
     *
     * @param request
     * @return
     */
    public S012A updateStockinAndDetail(S012R request) {
        //更新入库单信息
        TsStockInFlow stockInFlow = stockInFlowService.selectById(request.getStockId());

        stockInFlow.setStockDate(DateUtil.parse(request.getStockDate(), "yyyy-MM-dd"));
        stockInFlow.setStockType(request.getStockType());
        stockInFlow.setStorCode(request.getStorCode());
        stockInFlow.setDigest(request.getDigest());
        stockInFlow.setSourBillType(request.getSourBillType());
        stockInFlow.setSourBillId(request.getSourBillId());
        stockInFlow.setMtime(new Date());
        boolean result = stockInFlowService.updateById(stockInFlow);

        //更新入库单明细
        Wrapper<TsStockInDetailFlow> wrapper = new EntityWrapper<>();
        wrapper.eq("mem_code", request.getMemCode())
                .and().eq("stock_id", request.getStockId())
                .and().eq("stat", PubStatEnum.STAT_NORMAL.getCode());
        List<TsStockInDetailFlow> stockInDetailFlows = stockInDetailFlowService.selectList(wrapper);
        stockInDetailFlows.forEach(entity -> {
            entity.setStat(PubStatEnum.STAT_STOP.getCode());
            entity.setMtime(new Date());
        });

        if (CollectionUtil.isNotEmpty(stockInDetailFlows)) {
            stockInDetailFlowService.updateBatchById(stockInDetailFlows);
        }

        //新增入库单明细
        List<TsStockInDetailFlow> stockInDetailFlowList = convert2EntityList(request.getStockDetailInfos(), stockInFlow);
        boolean detailResult = stockInDetailFlowService.insertBatch(stockInDetailFlowList);
        S012A response = new S012A();
        response.setStockId(stockInFlow.getId().toString());
        return response;
    }

    /**
     * 转换为入库单明细实体
     *
     * @param stockDetailInfos
     * @return
     */
    private List<TsStockInDetailFlow> convert2EntityList(List<StockDetailInfo> stockDetailInfos, TsStockInFlow stockInFlow) {
        Map<Integer, String> goodNameList = goodsInfoService.getGoodNameList(stockInFlow.getMemCode());
        List<TsStockInDetailFlow> stockInDetailFlows = new ArrayList<>();
        stockDetailInfos.forEach(stockDetailInfo -> {
            TsStockInDetailFlow entity = new TsStockInDetailFlow();
            BeanUtil.copyPropertiesIgnoreNull(stockDetailInfo, entity);
            entity.setMemCode(stockInFlow.getMemCode());
            entity.setGoodName(goodNameList.get(stockDetailInfo.getGoodCode()));
            entity.setStockId(stockInFlow.getId().toString());

            stockInDetailFlows.add(entity);
        });

        return stockInDetailFlows;
    }

    /**
     * 删除修改入库单状态为已作废
     *
     * @param request
     * @return
     */
    public S011A delStockinBill(S011R request) {
        TsStockInFlow stockInFlow = stockInFlowService.selectById(request.getStockId());
        stockInFlow.setStat(PubStatEnum.STAT_STOP.getCode());

        boolean result = stockInFlowService.updateById(stockInFlow);
        S011A response = new S011A();
        response.setStockId(stockInFlow.getId());
        return response;
    }

    public boolean updateVerfitation(Integer verfierId, Integer stockId, Integer verfyStat, String verfyErrMsg) {
        TsStockInFlow entity = stockInFlowService.selectById(stockId);

        entity.setVerfyStat(verfyStat);
        if (VerfyStatEnum.VERFY_STAT_FAIL.getCode() == verfyStat) {
            entity.setVerfyErrMsg(verfyErrMsg);
            entity.setVerfyDate(new Date());
        }
        entity.setVerfierId(verfierId);
        return stockInFlowService.updateById(entity);
    }

    /**
     * 审核通过
     * @param memCode
     * @param stockId
     * @return
     */
    public boolean verfyPassStockIn(Integer verfierId, int memCode, Integer stockId) {
        TsStockInFlow flow = stockInFlowService.selectById(stockId);

        Wrapper<TsStockInDetailFlow> wrapper = new EntityWrapper<>();
        wrapper.eq("mem_code", memCode)
                .and().eq("stock_id", stockId)
                .orderBy("id", true);

        // 查询入库单明细
        List<TsStockInDetailFlow> stockInDetailFlows = stockInDetailFlowService.selectList(wrapper);

        // 新增入库单明细
        storGoodsDetailInfoService.addStorageDetail(memCode, flow.getStorCode(), stockInDetailFlows);

        // 更新库存
        Map<Integer, BigDecimal> sumMap = new HashMap<>();
        Map<Integer, List<TsStockInDetailFlow>> groupMap = stockInDetailFlows.stream().collect(Collectors.groupingBy(TsStockInDetailFlow::getGoodCode));
        Iterator<Map.Entry<Integer, List<TsStockInDetailFlow>>> iterator = groupMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = iterator.next();
            List<TsStockInDetailFlow> flowList = (List<TsStockInDetailFlow>) entry.getValue();

            BigDecimal sum = BigDecimal.ZERO;
            flowList.forEach(stockInDetailFlow -> {
                sum.add(stockInDetailFlow.getAmount());
            });

            storGoodsInfoService.addStorage(memCode, flow.getStorCode(), (Integer) entry.getKey(), sum);
            // 生成库存变动流水
            storMsgFlowService.buildStorageMsg(memCode, flow.getStorCode(), (Integer) entry.getKey(), StorMsgTypeEnum.MSG_TYPE_STOCKIN.getCode(), sum);
        }
        boolean result = updateVerfitation(verfierId, stockId, VerfyStatEnum.VERFY_STAT_PASS.getCode(), null);
        return true;
    }

    /**
     * 审核不通过
     * @param memCode
     * @param stockId
     * @param errMsg
     * @param verfierId
     * @return
     */
    public boolean verfyNopassStockIn(Integer verfierId, int memCode, Integer stockId, String errMsg){
        return updateVerfitation(verfierId, stockId, VerfyStatEnum.VERFY_STAT_FAIL.getCode(), errMsg);
    }
}
